package de.traveltainment.concept.envers.repository;

import de.traveltainment.concept.envers.audit.lifecycle.Lifecycle;
import de.traveltainment.concept.envers.audit.lifecycle.Stage;
import de.traveltainment.concept.envers.entities.Vito;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by borlis on 17.06.2014.
 */
@RequestScoped
public class LifecycleRepositoy {

    @Inject
    private EntityManager em;

    @Inject
    private Logger logger;

    public Lifecycle create(Lifecycle lifecycle) throws Exception {
        try {
            if (em.getTransaction().isActive()) {
                //em.joinTransaction();
                em.persist(lifecycle);
            } else {
                em.getTransaction().begin();
                em.persist(lifecycle);
                if (!em.getTransaction().isActive())
                    em.getTransaction().commit();
            }
            return lifecycle;
        } catch (PersistenceException error) {
            logger.log(Level.SEVERE, error.getMessage());
            em.getTransaction().rollback();
            throw new Exception(error);
        }
    }

    public void pullStages() throws Exception {
        try {
            em.getTransaction().begin();
            Query query = em.createNamedQuery("pullStages");
            query.executeUpdate();
            em.getTransaction().commit();
        } catch (PersistenceException error) {
            logger.log(Level.SEVERE, error.getMessage());
            em.getTransaction().rollback();
            throw new Exception(error);
        }
    }

    public Lifecycle merge(Stage stage) throws Exception {
        try {
            CriteriaBuilder builder = em.getCriteriaBuilder();
            CriteriaQuery<Lifecycle> criteria  = builder.createQuery(Lifecycle.class);
            Root<Lifecycle> from = criteria.from(Lifecycle.class);
            criteria.where(builder.and(
                    builder.equal(from.get("stage"), stage),
                    builder.equal(from.get("isActive"), 1)));
            TypedQuery<Lifecycle> query = em.createQuery(criteria);
            return query.getSingleResult();
        } catch (NoResultException error) {
            logger.log(Level.SEVERE, error.getMessage());
            Lifecycle lifecycle = new Lifecycle();
            lifecycle.setIsActive(1);
            lifecycle.setStage(stage);
            return create(lifecycle);
        }
    }

    public Lifecycle findWithStage(Long id, Stage stage) {
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Lifecycle> criteria  = builder.createQuery(Lifecycle.class);
        Root<Lifecycle> from = criteria.from(Lifecycle.class);
        criteria.where(builder.and(
                builder.equal(from.get("stage"), stage),
                builder.equal(from.get("isActive"), 1)),
                builder.equal(from.get("vitoId"), id));
        TypedQuery<Lifecycle> query = em.createQuery(criteria);
        return query.getSingleResult();
    }

    public void update(Lifecycle lastLive) {
        em.getTransaction().begin();
        em.merge(lastLive);
        em.getTransaction().commit();
    }


}
